package graphics;

import interfaces.IZbuffer;

import java.awt.Color;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.HashMap;

import classes.Vector;

public class Zbuffer implements IZbuffer {
	
	public static final class Zvalue {
		public final	float	Z;
		public final	Color	C;
		Zvalue(float Z, Color C) {
			this.Z = Z;
			this.C = C;
		}
		public static final int compare(Zvalue Z1, Zvalue Z2) {
			if (Z1.Z > Z2.Z)	return 1;
			if (Z1.Z < Z2.Z)	return -1;
			return 0;
		}
	}
	private	HashMap<Point, Zvalue>	buffer 		= new HashMap<Point, Zvalue>();
	private	Color					background	= new Color(128, 128, 128, 128);
	
	public void clear() {
		buffer.clear();
	}
	public void put(Vector V, Color C) {
		put(new Point((int) V.getX(),	(int) V.getY()),	new Zvalue(V.getZ(), C));
	}
	private void put(Point P, Zvalue newZ)	{
		Zvalue	oldZ = buffer.get(P);
		if	(	oldZ==null 
			||	oldZ.Z <= newZ.Z
			)
		{
			buffer.put(P, newZ);
		}
	}
	public Color get(Point P) {
		Zvalue zValue = buffer.get(P);
		if (zValue==null) {
			return background;
		} else {
			return zValue.C;
		}
	}

	public void	paintImage(BufferedImage img, int srcX, int srcY) {
		int width = img.getWidth();
		int height = img.getHeight();
		int	x = srcX;
		int y = srcY;
		
		Color	C;
		
		for ( int rc = 0; rc < height; rc++ ) {
			for ( int cc = 0; cc < width; cc++ ) {
				C = getPixel(cc+x, rc+y);
				img.setRGB(cc, rc, C.getRGB() );
			}
		}
	}
	
	public BufferedImage getArea(Rectangle R) {
		// Create the new image needed
		int				width = R.width;
		int 			height = R.height;
		BufferedImage	img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB );
		paintImage(img, R.x, R.y);
		return img;
	}
	
	@Override
	public void setPixel(int x, int y, float z, Color c) {
		put(new Point(x,y), new Zvalue(x, c));
	}
	@Override
	public Color getPixel(int x, int y) {
		return get(new Point(x,y));
	}
	@Override
	public int getWidth() {
		return Integer.MAX_VALUE;
	}
	@Override
	public int getHeight() {
		return Integer.MIN_VALUE;
	}
	
	
}
